package com.sz.biz.logistics.base.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.base.entity.Country;
import com.sz.biz.logistics.base.entity.Ship;
import com.sz.biz.logistics.base.entity.ShippingCompany;
import com.sz.biz.common.base.service.AreaManager;
import com.sz.biz.logistics.base.service.ShipService;
import com.sz.biz.logistics.base.service.ShippingCompanyService;
import com.sz.biz.logistics.base.dto.ShipDto;
import com.sz.common.base.cache.EntityCache;
import com.sz.common.base.constants.AppDomain;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.DaoSupport;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.I18nDto;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.service.SysFileGroupService;
import com.sz.common.core.system.service.SysFileService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Function: 船舶ShipServiceImpl <br>
 * Author: wentao.chang <br>
 * Date: 2017-08-04 15:41:00
 */
@Service("shipService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ShipServiceImpl extends AbstractService implements ShipService {
    @Autowired
    SysFileService fileService;
    @Autowired
    ShippingCompanyService shippingCompanyService;

    @Autowired
    SysFileGroupService fileGroupService;
    @Autowired
    AreaManager areaManager;

    @Resource(name = "daoSupport")
    private DaoSupport dao;

    @Override
    public void refreshCache() {
        EntityCache.clearNamespace("ShipMapper");
    }

    @Override
    public int save(ShipDto shipDto) {
        Ship ship = new Ship();
        EntityUtils.copyPropertiesIgnoreNull(shipDto, ship);
        // 检查数据不能重复
        checkNameEn(ship.getNameEn(), null);
        checkShipMMSI(ship.getMmsi(), null);
        checkImo(ship.getImo(), null);
        //处理附件
        List<String> attachments = shipDto.getAttachments();
        if (!CollectionUtils.isEmpty(attachments)) { //update file
            String fileGroupId = fileGroupService.createFileGroup(attachments, "biz.ship.model", null, AppDomain.OPERATION);
            ship.setPicture(fileGroupId);
        }
        ship.setCreateUserId(PrincipalUtils.getAccountId());
        ship.setLastUpdateUserId(PrincipalUtils.getAccountId());
        dao.save("ShipMapper.insert", ship);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_SHIP", ship);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SHIP, UserActions.ADD, "新建船舶",
                dataBackup);
        return ship.getId();
    }

    @Override
    public int update(Integer id, ShipDto shipDto) {
        Ship shipExist = findSimpleById(id);
        if (shipExist.getIsDeleted()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_DELETED, id);
        }
        Ship ship = new Ship();
        EntityUtils.copyPropertiesIgnoreNull(shipDto, ship);
        // 检查数据不能重复
        checkNameEn(ship.getNameEn(), id);
        checkShipMMSI(ship.getMmsi(), id);
        checkImo(ship.getImo(), id);
        String fileGroupId = fileGroupService.saveFileToGroup(shipExist.getPicture(), shipDto.getAttachments(),
                "biz.ship.model", null, AppDomain.OPERATION);
        ship.setPicture(fileGroupId);
        ship.setLastUpdateUserId(PrincipalUtils.getAccountId());
        ship.setId(id);
        dao.update("ShipMapper.update", ship);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_SHIP", ship);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SHIP, UserActions.UPDATE, "修改船舶",
                dataBackup);
        return id;
    }

    private void checkNameEn(String nameEn, Integer id) {
        Map<String, Object> map = new HashMap<>();
        map.put("nameEn", nameEn);
        map.put("id", id);
        Ship shipExist = (Ship) dao.findForObject("ShipMapper.checkNameEn", map);
        if (shipExist != null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_SHIP_NAMEEN_EXIST);
        }
    }

    @Override
    public void checkShipMMSI(String mmsi, Integer id) {
        Map<String, Object> map = new HashMap<>();
        map.put("mmsi", mmsi);
        map.put("id", id);
        Ship shipExist = (Ship) dao.findForObject("ShipMapper.checkMMSI", map);
        if (shipExist != null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_SHIP_MMSI_EXIST);
        }
    }

    @Override
    public void checkImo(String imo, Integer id) {
        Map<String, Object> map = new HashMap<>();
        map.put("imo", imo);
        map.put("id", id);
        Ship shipExist = (Ship) dao.findForObject("ShipMapper.checkIMO", map);
        if (shipExist != null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_SHIP_IMO_EXIST);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteByIds(List<Integer> ids) {
        dao.update("ShipMapper.deleteByIds", ids);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_SHIP", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SHIP, UserActions.DELETE, "删除船舶",
                dataBackup);

    }

    @Override
    public ShipDto findById(int id) {
        ParamData pd = new ParamData();
        pd.put("id", id);
        pd.put("language", PrincipalUtils.getLocalLanguage());
        Ship ship = (Ship) dao.findForObject("ShipMapper.findById", pd);
        ShipDto shipDto = new ShipDto();
        BeanUtils.copyProperties(ship, shipDto);
        if(ship.getCompanyId()!=null){
            ShippingCompany shippingCompany = shippingCompanyService.findSimpleById(ship.getCompanyId());
            shipDto.setCompanyName(shippingCompany.getName());
        }
        if (shipDto.getId() != null) {
            int refId = shipDto.getId();
            ParamData pdi18n = new ParamData();
            pdi18n.put("refId", refId);
            List<I18nDto> i18n = dao.findForList("ShipMapper.findShipI18n", pdi18n, I18nDto.class);
            shipDto.setI18n(i18n);
            if (!StringUtils.isEmpty(shipDto.getPicture())) {
                shipDto.setFiles(fileGroupService.getFileDtosByGroupId(shipDto.getPicture()));
            }
        }
        return shipDto;
    }


    @Override
    public ResultDto findShipListPage(QueryParams params) {
        String language = PrincipalUtils.getLocalLanguage();
        params.setLanguage(language);
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<Ship> list = dao.findForList("ShipMapper.shipListPage", pd, Ship.class);
        List<ShipDto> dtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(ship -> {
                ShipDto dto = new ShipDto();
                BeanUtils.copyProperties(ship, dto);
                Country country = areaManager.findByCountryCode(ship.getCountryId());
                dto.setCountryName(country.getName());
                if(ship.getCompanyId()!=null){
                    ShippingCompany shippingCompany = shippingCompanyService.findSimpleById(ship.getCompanyId());
                    dto.setCompanyName(shippingCompany.getName());
                }
                dtos.add(dto);
            });
        }
        QResultDto dto = new QResultDto();
        dto.setData(dtos);
        dto.setPagination(pd.getPagination());
        return dto;
    }


    /**
     * 根据shipId查询船舶信息
     *
     * @param ShipId ShipId
     * @return Ship
     */
    @Override
    public Ship findSimpleById(int ShipId) {
        ParamData pd = new ParamData();
        pd.put("id", ShipId);
        pd.put("language", PrincipalUtils.getLocalLanguage());
        return (Ship) dao.findForObject("ShipMapper.findById", pd);
    }

    /**
     * 根据shippingCompanyId查询船运公司信息
     *
     * @param shippingCompanyId shippingCompanyId
     * @return Ship
     */
    @Override
    public List<Ship> findByCompanyId(int shippingCompanyId) {
        return dao.findForList("ShipMapper.findByCompanyId",shippingCompanyId,Ship.class);
    }
    /**
     * 根据条件分页查询船舶短接口
     *
     * @param params params
     * @return ResultDto
     */
    @Override
    public ResultDto findShipShortListPage(QueryParams params) {
        String language = PrincipalUtils.getLocalLanguage();
        params.setLanguage(language);
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<Ship> list = dao.findForList("ShipMapper.shipShortListPage", pd, Ship.class);
        QResultDto dto = new QResultDto();
        dto.setData(list);
        dto.setPagination(pd.getPagination());
        return dto;
    }

    @Override
    public ResultDto findI18nByParam(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        List entry = dao.findForList(getSqlName("findI18nByParamListPage"), pd, Map.class);
        return new QResultDto(entry, pd.getPagination());
    }

    /**
     * 船舶英文名称校验
     *
     * @param nameEn nameEn
     * @param id     id
     */
    @Override
    public void checkShipNameEn(String nameEn, Integer id) {
        checkNameEn(nameEn, id);
    }

    @Override
    protected String getMapperNamespace() {
        return "ShipMapper";
    }
}
